import { useCallback, useMemo, useRef } from "react";
import styles from './index.less'
import { ComponentToolbar } from "@/pages/diagnose/generate/Pannel/components/componentToolbar";
import { CreateComponent } from "@/pages/diagnose/generate/Pannel/components/createComponent";
import { useDrag, useDrop } from "react-dnd";
import { GlobalItemType } from "@/pages/diagnose/generate/Pannel/constants/item";
import { componentConfigs } from "../../component-config";
import { usePanelGeneratorStore } from "@/pages/diagnose/generate/Pannel/store/panelGeneratorStore";

/**
 * component container
 * @param {Object} value
 * @param {number} displayIndex
 * @param {number} index
 * @returns {JSX.Element}
 * @constructor
 */
export const ComponentContainer = ({ value, displayIndex, index, savePrev, rowKey }) => {
    const configStore = usePanelGeneratorStore((state) => state.data)
    const setConfigStore = usePanelGeneratorStore((state) => state.setConfigStore)
    const ref = useRef(null)
    const container = componentConfigs[value.type].container
    const [{ display }, drag, preview] = useDrag(() => ({
        type: rowKey ? GlobalItemType.ROW_COMPONENT : GlobalItemType.COMPONENT,
        item: () => {
            return { index: index }
        },
        collect: (monitor) => ({
            opacity: monitor.isDragging() ? 0 : 1,
            display: monitor.isDragging() ? 'block' : 'none',
        }),
    }))
    const moveCard = useCallback((dragIndex, hoverIndex) => {
        savePrev.then(() => {
            setConfigStore((prev) => {
                if (container === 'taskform') {
                    const currentForm = prev.taskform
                    const dragCard = currentForm[dragIndex]
                    currentForm.splice(dragIndex, 1)
                    currentForm.splice(hoverIndex, 0, dragCard)
                    return {
                        ...prev,
                        taskform: currentForm
                    }
                }
                else if (container === 'panels') {
                    if (rowKey) {
                        const currentPanel = prev.pannels
                        const currentRow = currentPanel.find((item) => item?.key === rowKey)
                        const dragCard = currentRow.children[dragIndex]
                        currentRow.children.splice(dragIndex, 1)
                        currentRow.children.splice(hoverIndex, 0, dragCard)
                        return {
                            ...prev,
                            pannels: currentPanel.map((item) => {
                                if (item?.key === rowKey) {
                                    return currentRow
                                }
                                return item
                            })
                        }
                    } else {
                        const currentPanel = prev.pannels
                        const dragCard = currentPanel[dragIndex]
                        currentPanel.splice(dragIndex, 1)
                        currentPanel.splice(hoverIndex, 0, dragCard)
                        return {
                            ...prev,
                            pannels: currentPanel
                        }
                    }
                }
            }
            )
        })
    }, [])
    const [{ handlerId }, drop] = useDrop({
        accept: rowKey ? GlobalItemType.ROW_COMPONENT : GlobalItemType.COMPONENT,
        collect(monitor) {
            return {
                handlerId: monitor.getHandlerId(),
            }
        },
        hover(item, monitor) {
            if (!ref.current) {
                return
            }
            const dragIndex = item.index
            const hoverIndex = index
            // 去掉自己拖拽到自己身上的情况
            if (dragIndex === hoverIndex) {
                return
            }
            // 获取组件盒子边界
            const hoverBoundingRect = ref.current?.getBoundingClientRect()
            // 获取中间的位置
            const hoverMiddleX =
                (hoverBoundingRect.right - hoverBoundingRect.left) / 2
            // 获取鼠标位置
            const clientOffset = monitor.getClientOffset()
            // 获取拖拽距离左边的偏移量
            const hoverClientX = clientOffset.x - hoverBoundingRect.left
            // 拖拽的组件不是当前组件，而且超过了一半就交换位置
            // 拖拽判断
            if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
                return
            }
            // 拖拽
            if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
                return
            }
            // 移动顺序
            moveCard(dragIndex, hoverIndex)
            item.index = hoverIndex
        },
    })
    preview(drop(ref))
    return (
        <div ref={ref} className={styles.item} data-handler-id={handlerId}>
            <div className={styles.indicator} style={{ display: display }}></div>
            <ComponentToolbar displayIndex={displayIndex} index={index} value={value} drag={drag} preview={preview} rowKey={rowKey} />
            {useMemo(() =>
                <CreateComponent type={value.type} value={value} />
                , [configStore])}
        </div>
    )
}
